#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__

#include <memory>
#include <vector>
#include <functional>
#include <pthread.h>
#include "Poller/epoller.h"
#include "Base/mutex.h"
#include "Base/noncopyable.h"

#include "Timer/timerqueue.h"

namespace tiny_muduo
{
    class Channel;

    class EventLoop : public NonCopyable
    {
    public:
        typedef std::vector<Channel*> Channels;
        typedef std::function<void()> BasicFunc;
        typedef std::vector<BasicFunc> ToDoList;

        EventLoop();
        ~EventLoop();

        void RunAt(Timestamp timestamp, BasicFunc cb)
        {
            timer_queue_->AddTimer(timestamp, std::move(cb), 0.0);
        }

        void RunAfter(double wait_time, BasicFunc cb)
        {
            Timestamp timestamp(Timestamp::AddTime(Timestamp::Now(), wait_time));
            timer_queue_->AddTimer(timestamp, std::move(cb), 0.0);
        }

        void RunEvery(double interval, BasicFunc cb)
        {
            Timestamp timestamp(Timestamp::AddTime(Timestamp::Now(), interval));
            timer_queue_->AddTimer(timestamp, std::move(cb), interval);
        }

        bool IsInThreadLoop() { return ::pthread_self() == tid_; }
        void Update(Channel* channel) { epoller_->Update(channel); }
        void Remove(Channel* channel) { epoller_->Remove(channel); }
        
        void Loop();
        void HandleRead();
        void QueueOneFunc(const BasicFunc& func);
        void RunOneFunc(const BasicFunc& func);
        void DoToDoList();

        pthread_t DebugShowTid() { return tid_; }

    private:
        pthread_t tid_;
        std::unique_ptr<Epoller> epoller_;
        int wakeup_fd_;
        std::unique_ptr<Channel> wakeup_channel_;
        std::unique_ptr<TimerQueue> timer_queue_;
        bool calling_functors_;
        Channels active_channels_;
        ToDoList to_do_list;

        MutexLock mutex_;
    };
}

#endif
